/*
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.1 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
 * License for the specific language governing rights and limitations
 * under the License.
 * 
 * The Original Code is iSQL-Viewer, A Mutli-Platform Database Tool.
 *
 * The Initial Developer of the Original Code is iSQL-Viewer, A Mutli-Platform Database Tool.
 * Portions created by Mark A. Kobold are Copyright (C) 2000-2007. All Rights Reserved.
 *
 * Contributor(s): 
 *  Mark A. Kobold [mkobold <at> isqlviewer <dot> com].
 *  
 * If you didn't download this code from the following link, you should check
 * if you aren't using an obsolete version: http://www.isqlviewer.com
 */
package org.isqlviewer.swing;

import javax.swing.event.EventListenerList;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.TreeModel;

import org.isqlviewer.util.LoggableObject;

/**
 * Base class for tree models.
 * <p>
 * Since the JDK does not provide any kind of abstract tree model where it really just implements the model listener
 * code, i.e. AbstractTableModel. This class is here to remedy that lacking, since often the DefaultTreeModel is
 * cumbersome to work with dealing with all those TreeNode classes.
 * <p>
 * All this class does implements is your basic fireXXXX methods for TreeModelListeners and has the implementation for
 * adding and removing those listeners from the model every thing else is up to childeren of this class.
 * 
 * @author Markus A. Kobold &lt;mkobold at sprintpcs dot com&gt;
 */
public abstract class AbstractTreeModel extends LoggableObject implements TreeModel {

    protected transient EventListenerList eventListeners = new EventListenerList();

    public synchronized final void removeTreeModelListener(TreeModelListener l) {

        eventListeners.remove(TreeModelListener.class, l);
    }

    public synchronized final void addTreeModelListener(TreeModelListener l) {

        eventListeners.add(TreeModelListener.class, l);
    }

    /**
     * Utility method for notifying listeners that the enitre tree has been reloaded.
     * <p>
     * All this method does is dispatch a TreeModelEvent with the root node of this model.
     * 
     * @see #fireTreeStructureChanged(TreeModelEvent)
     */
    public void reload() {

        fireTreeStructureChanged(new TreeModelEvent(this, new Object[]{getRoot()}, null, null));
    }

    /**
     * Notifies the model listeners of a treeNodesChanged event.
     * <p>
     * Iterates through the current listener list, and calls the treeNodesChanged method for the listener. If the model
     * listener throws an an exception or error it will be silently ignored and this method will continue to dispatch
     * the event until all listeners have been notified.
     * 
     * @see TreeModelListener#treeNodesChanged(javax.swing.event.TreeModelEvent)
     * @param e TreeModelEvent to dispatch.
     */
    protected void fireTreeNodesChanged(TreeModelEvent e) {

        TreeModelListener[] listenerList = eventListeners.getListeners(TreeModelListener.class);
        if (listenerList != null) {
            for (int i = 0; i < listenerList.length; i++) {
                try {

                    listenerList[i].treeNodesChanged(e);
                } catch (Exception error) {
                    error("Error Dispatching TreeEvent(" + e + ")", error);
                }
            }
        }
    }

    /**
     * Notifies the model listeners of a treeNodesInserted event.
     * <p>
     * Iterates through the current listener list, and calls the treeNodesInserted method for the listener. If the model
     * listener throws an an exception or error it will be silently ignored and this method will continue to dispatch
     * the event until all listeners have been notified.
     * 
     * @see TreeModelListener#treeNodesInserted(javax.swing.event.TreeModelEvent)
     * @param e TreeModelEvent to dispatch.
     */
    protected void fireTreeNodesInserted(TreeModelEvent e) {

        TreeModelListener[] listenerList = eventListeners.getListeners(TreeModelListener.class);
        if (listenerList != null) {
            for (int i = 0; i < listenerList.length; i++) {
                try {
                    listenerList[i].treeNodesInserted(e);
                } catch (Exception error) {
                    error("Error Dispatching TreeEvent(" + e + ")", error);
                }
            }
        }
    }

    /**
     * Notifies the model listeners of a treeNodesRemoved event.
     * <p>
     * Iterates through the current listener list, and calls the treeNodesRemoved method for the listener. If the model
     * listener throws an an exception or error it will be silently ignored and this method will continue to dispatch
     * the event until all listeners have been notified.
     * 
     * @see TreeModelListener#treeNodesRemoved(javax.swing.event.TreeModelEvent)
     * @param e TreeModelEvent to dispatch.
     */
    protected void fireTreeNodesRemoved(TreeModelEvent e) {

        TreeModelListener[] listenerList = eventListeners.getListeners(TreeModelListener.class);
        if (listenerList != null) {
            for (int i = 0; i < listenerList.length; i++) {
                try {
                    listenerList[i].treeNodesRemoved(e);
                } catch (Exception error) {
                    error("Error Dispatching TreeEvent(" + e + ")", error);
                }
            }
        }
    }

    /**
     * Notifies the model listeners of a treeStructureChanged event.
     * <p>
     * Iterates through the current listener list, and calls the treeStructureChanged method for the listener. If the
     * model listener throws an an exception or error it will be silently ignored and this method will continue to
     * dispatch the event until all listeners have been notified.
     * 
     * @see TreeModelListener#treeStructureChanged(javax.swing.event.TreeModelEvent)
     * @param e TreeModelEvent to dispatch.
     */
    protected void fireTreeStructureChanged(TreeModelEvent e) {

        TreeModelListener[] listenerList = eventListeners.getListeners(TreeModelListener.class);
        if (listenerList != null) {
            for (int i = 0; i < listenerList.length; i++) {
                try {
                    listenerList[i].treeStructureChanged(e);
                } catch (Exception error) {
                    error("Error Dispatching TreeEvent(" + e + ")", error);
                }
            }
        }
    }
}